#region License
// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)
/*
 * This license governs use of the accompanying software. If you use the software, you
 * accept this license. If you do not accept the license, do not use the software.
 * 
 * 1. Definitions
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
 * same meaning here as under U.S. copyright law.
 * A "contribution" is the original software, or any additions or changes to the software.
 * A "contributor" is any person that distributes its contribution under this license.
 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 * 
 * 2. Grant of Rights
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions 
 *     and limitations in section 3, each contributor grants you a non-exclusive, worldwide, 
 *     royalty-free copyright license to reproduce its contribution, prepare derivative works 
 *     of its contribution, and distribute its contribution or any derivative works that you create.
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and 
 *     limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free 
 *     license under its licensed patents to make, have made, use, sell, offer for sale, import, 
 *     and/or otherwise dispose of its contribution in the software or derivative works of the 
 *     contribution in the software.
 * 
 * 3. Conditions and Limitations
 * (A) No Trademark License- This license does not grant you rights to use any contributors' 
 *     name, logo, or trademarks.
 * (B) If you bring a patent claim against any contributor over patents that you claim are 
 *     infringed by the software, your patent license from such contributor to the software 
 *     ends automatically.
 * (C) If you distribute any portion of the software, you must retain all copyright, patent, 
 *     trademark, and attribution notices that are present in the software.
 * (D) If you distribute any portion of the software in source code form, you may do so only under 
 *     this license by including a complete copy of this license with your distribution. If you 
 *     distribute any portion of the software in compiled or object code form, you may only do so 
 *     under a license that complies with this license.
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no 
 *     express warranties, guarantees or conditions. You may have additional consumer rights under 
 *     your local laws which this license cannot change. To the extent permitted under your local laws, 
 *     the contributors exclude the implied warranties of merchantability, fitness for a particular 
 *     purpose and non-infringement.
 * 
 */
#endregion

using System;
using System.Runtime.InteropServices;

namespace NPack
{
    [StructLayout(LayoutKind.Sequential)]
    public struct DoubleComplex : IComparable<DoubleComplex>, IComparable<Double>, IComparable,
                                  IEquatable<DoubleComplex>, IEquatable<Double>
    {
        private readonly Double _real;
        private readonly Double _imaginary;

        public DoubleComplex(Double real, Double imaginary)
        {
            _real = real;
            _imaginary = imaginary;
        }

        public override String ToString()
        {
            return String.Format("{0:N8} + {1:N8}i", _real, _imaginary);
        }

        public override Int32 GetHashCode()
        {
            return _real.GetHashCode() ^ _imaginary.GetHashCode();
        }

        public Double Real
        {
            get { return _real; }
        }

        public Double Imaginary
        {
            get { return _imaginary; }
        }

        public static DoubleComplex operator -(DoubleComplex value)
        {
            return new DoubleComplex(-value._real, -value._imaginary);
        }

        public static DoubleComplex operator +(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real + rhs._real, lhs._imaginary + rhs._imaginary);
        }

        public static DoubleComplex operator +(DoubleComplex lhs, Double rhs)
        {
            return new DoubleComplex(lhs._real + rhs, lhs._imaginary);
        }

        public static DoubleComplex operator +(Double lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs + rhs._real, rhs._imaginary);
        }

        public static DoubleComplex operator -(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real - rhs._real, lhs._imaginary - rhs._imaginary);
        }

        public static DoubleComplex operator -(Double lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs - rhs._real, rhs._imaginary);
        }

        public static DoubleComplex operator -(DoubleComplex lhs, Double rhs)
        {
            return new DoubleComplex(lhs._real - rhs, lhs._imaginary);
        }

        public static DoubleComplex operator *(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real*rhs._real, lhs._imaginary*rhs._imaginary);
        }

        public static DoubleComplex operator /(DoubleComplex lhs, DoubleComplex rhs)
        {
            return new DoubleComplex(lhs._real/rhs._real, lhs._imaginary/rhs._imaginary);
        }

        public static explicit operator SingleComplex(DoubleComplex value)
        {
            return new SingleComplex((Single) value._real, (Single) value._imaginary);
        }

        #region IComparable<DoubleComplex> Members

        public Int32 CompareTo(DoubleComplex other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IComparable<Double> Members

        public Int32 CompareTo(Double other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IComparable Members

        public Int32 CompareTo(Object obj)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IEquatable<DoubleComplex> Members

        public Boolean Equals(DoubleComplex other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IEquatable<Double> Members

        public Boolean Equals(Double other)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }
}